{
 "nbformat": 4,
 "nbformat_minor": 2,
 "metadata": {
  "language_info": {
   "name": "python",
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   }
  },
  "orig_nbformat": 2,
  "file_extension": ".py",
  "mimetype": "text/x-python",
  "name": "python",
  "npconvert_exporter": "python",
  "pygments_lexer": "ipython3",
  "version": 3
 },
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Hyperparameters\n",
    "stocks = ['AAPL', 'MSFT', 'GOOG', 'AMZN', 'FB', 'BABA', 'INTC', 'NVDA', 'CRM', 'PYPL', 'TSLA', 'AMD', 'ATVI', 'EA', 'MTCH', 'TTD', 'ZG', 'YELP', 'TIVO']\n",
    "num_stocks_to_invest_in = 10\n",
    "DAYS = 100\n",
    "sell_all_at_market_close = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# Initialize API\n",
    "import alpaca_trade_api as tradeapi\n",
    "\n",
    "API_KEY = 'your-key-id'\n",
    "SECRET_KEY = 'your-secret-key'\n",
    "BASE_URL = 'https://paper-api.alpaca.markets'\n",
    "\n",
    "api = tradeapi.REST(key_id=API_KEY, secret_key=SECRET_KEY, base_url=BASE_URL, api_version='v2')\n",
    "\n",
    "account = api.get_account()\n",
    "budget = float(account.buying_power)\n",
    "print(f'Your budget is: {budget}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Get live price of share\n",
    "import bs4 as bs\n",
    "import requests\n",
    "\n",
    "message = \"\"\"At the time of writing https://marketwatch.com/robots.txt does not disallow web scraping https://www.marketwatch.com/investing/stock/*. With this said, I cannot guarantee this for the future, so please check their robots.txt before continuing. I am not responsible for any actions you may take.  After verifying that marketwatch.com still allows scraping this part of their site, please manually set I_UNDERSTAND to True\"\"\"\n",
    "I_UNDERSTAND = False\n",
    "\n",
    "if not I_UNDERSTAND:\n",
    "    raise UserWarning\n",
    "\n",
    "def get_live_price(ticker):\n",
    "    while True:\n",
    "        try:\n",
    "            # Send request to marketwatch.com for the given ticker\n",
    "            resp = requests.get(f\"https://www.marketwatch.com/investing/stock/{ticker.replace('-', '.')}\")\n",
    "            soup = bs.BeautifulSoup(resp.text, features='lxml')\n",
    "\n",
    "            # Find HTML element on the page\n",
    "            value = soup.find('bg-quote', {'class': 'value'})\n",
    "\n",
    "            # Read its value\n",
    "            return float(value.text.replace(',', ''))\n",
    "        except Exception:\n",
    "            continue"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Get barset data of stock(s) into pd.DataFrame format\n",
    "import pandas as pd\n",
    "\n",
    "def get_pandas_barset(symbols, timeframe, limit, start=None, end=None, after=None, until=None):\n",
    "    barset = api.get_barset(symbols, timeframe, limit, start, end, after, until)\n",
    "    dataframes = {}\n",
    "    \n",
    "    for symbol in barset.keys():\n",
    "        bars = barset[symbol]\n",
    "\n",
    "        data = {'close': [bar.c for bar in bars],\n",
    "                'high': [bar.h for bar in bars],\n",
    "                'low': [bar.l for bar in bars],\n",
    "                'open': [bar.o for bar in bars],\n",
    "                'time': [bar.t for bar in bars],\n",
    "                'volume': [bar.v for bar in bars]}\n",
    "        \n",
    "        dataframes[symbol] = pd.DataFrame(data)\n",
    "    \n",
    "    return dataframes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sell everything owned\n",
    "print('Selling all current positions...')\n",
    "api.cancel_all_orders()\n",
    "positions = api.list_positions()\n",
    "\n",
    "for position in positions:\n",
    "    api.submit_order(\n",
    "        symbol=position.symbol,\n",
    "        qty=position.qty,\n",
    "        side='sell',\n",
    "        type='market',\n",
    "        time_in_force='gtc'\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calculate percent increases for each stock in the past d days\n",
    "print('Calculating increases...')\n",
    "stock_data = get_pandas_barset(stocks, 'day', DAYS)\n",
    "\n",
    "percent_increases = [] # could also use ordered dict for this\n",
    "\n",
    "for symbol in stocks:\n",
    "    percent_increases.append((symbol, stock_data[symbol].iloc[-1].close/stock_data[symbol].iloc[0].close - 1))\n",
    "\n",
    "percent_increases = sorted(percent_increases, key=lambda x: x[1], reverse=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Divvy up budget to each stock\n",
    "print('Calculating how many stocks to buy...')\n",
    "total_increase_sum = 0\n",
    "\n",
    "for symbol, increase in percent_increases[:num_stocks_to_invest_in]:\n",
    "    total_increase_sum += increase\n",
    "\n",
    "shares_to_buy = {}\n",
    "\n",
    "for symbol, increase in percent_increases[:num_stocks_to_invest_in]:\n",
    "    shares_to_buy[symbol] = budget*(increase/(total_increase_sum*get_live_price(symbol)))\n",
    "\n",
    "print(shares_to_buy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Send requests to Alpaca API to buy shares\n",
    "print('Buying shares...')\n",
    "import math\n",
    "\n",
    "for symbol in shares_to_buy.keys():\n",
    "    if shares_to_buy[symbol] >= 1:\n",
    "        api.submit_order(\n",
    "            symbol=symbol,\n",
    "            qty=math.floor(shares_to_buy[symbol]),\n",
    "            side='buy',\n",
    "            type='market',\n",
    "            time_in_force='gtc'\n",
    "        )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sell everything at the end of the day\n",
    "import time, datetime\n",
    "\n",
    "if sell_all_at_market_close:\n",
    "    clock = api.get_clock()\n",
    "    seconds = (clock.next_close - clock.timestamp - datetime.timedelta(minutes=10)).total_seconds()\n",
    "    print('Waiting', seconds, 'seconds until market is nearly closed.')\n",
    "    time.sleep(seconds)\n",
    "\n",
    "    api.cancel_all_orders()\n",
    "    positions = api.list_positions()\n",
    "\n",
    "    for position in positions:\n",
    "        api.submit_order(\n",
    "            symbol=position.symbol,\n",
    "            qty=position.qty,\n",
    "            side='sell',\n",
    "            type='market',\n",
    "            time_in_force='gtc'\n",
    "        )"
   ]
  }
 ]
}